package com.liurong.util.redis;

import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisTemplate {
	private Logger logger = LoggerFactory.getLogger(RedisTemplate.class);
	private JedisPool jedisPool;

	public void setJedisPool(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}

	public Set<String> keys(String pattern) {
		Jedis jedis = null;
		Set<String> result = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.keys(pattern);
		} catch (Exception e) {
			logger.error("redisTemplate keys error {},", pattern, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	public String set(String key, String value) {
		Jedis jedis = null;
		String result = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.set(key, value);
		} catch (Exception e) {
			logger.error("redisTemplate set error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	public String get(String key) {
		Jedis jedis = null;
		String result = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.get(key);
		} catch (Exception e) {
			logger.error("redisTemplate get error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	public Long lpush(String key, String... values) {
		Jedis jedis = null;
		Long result = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.lpush(key, values);
		} catch (Exception e) {
			logger.error("redisTemplate lpush error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	public String rpop(String key) {
		Jedis jedis = null;
		String result = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.rpop(key);
		} catch (Exception e) {
			logger.error("redisTemplate rpop error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	/**
	 * 分布式锁
	 * 
	 * @param key
	 * @param lockTime
	 *            锁定时间--毫秒
	 * @param timeouts
	 *            超时时间--毫秒
	 * @return
	 */
	public boolean lock(String key, long lockTime, long timeouts) {
		Jedis jedis = null;
		boolean result = false;
		long timeoutsTime = System.currentTimeMillis() + timeouts;
		key = "jedis_lock_" + key;
		try {
			while (true) {
				jedis = jedisPool.getResource();
				if (jedis.setnx(key, key) == 1) {
					if (jedis.pexpire(key, lockTime) == 1) {
						result = true;
						break;
					}
				}
				if ((timeoutsTime - System.currentTimeMillis()) <= 0) {
					break;
				}

				// 发生死锁了，锁定时间重置
				if (jedis.ttl(key) == -1) {
					jedis.pexpire(key, lockTime);
				}

				// 休眠之前把链接放回连接池，不要让一个线程一直占链接。不然将导致链接不够用的情况
				// 这里的关闭，并不是关闭链接。而是将链接换给线程池
				jedis.close();
				TimeUnit.MILLISECONDS.sleep(10);// 休息10毫秒
			}
		} catch (Exception e) {
			logger.error("redisTemplate lock error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	/**
	 * 分布式锁
	 * 
	 * @param key
	 * @param lockTime
	 *            锁定时间--毫秒
	 * @param timeouts
	 *            超时时间--毫秒
	 * @return
	 */
	public boolean lock(String key, String value, long lockTime, long timeouts) {
		Jedis jedis = null;
		boolean result = false;
		long timeoutsTime = System.currentTimeMillis() + timeouts;
		key = "jedis_lock_" + key;
		try {
			while (true) {
				jedis = jedisPool.getResource();
				if (jedis.setnx(key, value) == 1) {
					if (jedis.pexpire(key, lockTime) == 1) {
						result = true;
						break;
					}
				}
				if ((timeoutsTime - System.currentTimeMillis()) <= 0) {
					break;
				}

				// 发生死锁了，锁定时间重置
				if (jedis.ttl(key) == -1) {
					jedis.pexpire(key, lockTime);
				}

				// 休眠之前把链接放回连接池，不要让一个线程一直占链接。不然将导致链接不够用的情况
				jedis.close();
				TimeUnit.MILLISECONDS.sleep(10);// 休息10毫秒
			}
		} catch (Exception e) {
			logger.error("redisTemplate lock error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return result;
	}

	/**
	 * 释放锁
	 * 
	 * @param key
	 */
	public void releaseLock(String key) {
		Jedis jedis = null;
		key = "jedis_lock_" + key;
		try {
			jedis = jedisPool.getResource();
			jedis.del(key);
		} catch (Exception e) {
			logger.error("redisTemplate releaseLock error {},", key, e);
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
}
